#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace GameStateManagement
{
    /// <summary>
    /// This screen implements the actual game logic.
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;
        SpriteFont scoreFont;
        float pauseAlpha;
        Random random = new Random();
        float triggerActivate = 0.85f; // The amount needed to be pressed to activate the trigger.

        Stopwatch stopWatch = new Stopwatch();
        bool running = false;
        bool pause = false;
        bool wait = false;
        int currentRound = 0;
        int totalRounds = 10;
        float[] score = new float[10];

        float[] highscore = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
        string highscorer = "rivu";

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameFont = content.Load<SpriteFont>("gamefont");
            scoreFont = content.Load<SpriteFont>("scorefont");

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            if (IsActive)
            {
                // enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;

                /* Vector2 targetPosition = new Vector2(
                    ScreenManager.GraphicsDevice.Viewport.Width / 2 - gameFont.MeasureString("Insert Gameplay Here").X / 2, 
                    200); */

               // enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);

                // TODO: this game isn't very fun! You could probably improve
                // it by inserting something more interesting in this space :-)
            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {
                if(pause) {
                    if(stopWatch.ElapsedMilliseconds > 2000){
                        stopWatch.Reset();
                        stopWatch.Start();
                        pause = false;
                    }
                }
                else if(!running) {
                    if(keyboardState.IsKeyDown(Keys.Enter) || gamePadState.Triggers.Right > triggerActivate ||
                            gamePadState.IsButtonDown(Buttons.A)) {
                        running = true;
                        stopWatch.Reset();
                        stopWatch.Start();
                        wait = true;
                        pause = true;
                        score = new float[10];
                        // Enter the 'wait' state.
                    }
                } else {
                    if(wait) {
                        if (stopWatch.ElapsedMilliseconds > random.Next(5000,15000)) {
                            wait = false;
                            stopWatch.Reset();
                            stopWatch.Start();
                        } else if(keyboardState.IsKeyDown(Keys.Enter) || gamePadState.Triggers.Right > triggerActivate) {
                            score[currentRound] = 1.0f;
                            wait = true;
                            pause = true;
                            stopWatch.Reset();
                            stopWatch.Start();
                            currentRound++;
                        }
                    } else {
                        if(keyboardState.IsKeyDown(Keys.Enter) || gamePadState.Triggers.Right > triggerActivate) {
                            // Submit score
                            score[currentRound] = MathHelper.Clamp(stopWatch.ElapsedMilliseconds / 1000.0f, 0.0f, 1.0f);
                            // Enter the 'wait' state.
                            wait = true;
                            pause = true;
                            stopWatch.Reset();
                            stopWatch.Start();
                            currentRound++;
                        } else if(stopWatch.ElapsedMilliseconds > 1000) {
                            // Penalty
                            score[currentRound] = 1.0f;
                            // Enter the 'wait' state.
                            wait = true;
                            pause = true;
                            stopWatch.Reset();
                            stopWatch.Start();
                            currentRound++;
                        }
                    }
                    if(currentRound >= totalRounds) {
                        // End game
                        wait = true;
                        running = false;
                        pause = true;
                        stopWatch.Reset();
                        stopWatch.Start();
                        currentRound = 0;
                        if(getAvg(score) < getAvg(highscore)) {
                            highscore = score;
                            highscorer = "0xFFright";
                        }
                    }
                }
            }
        }

        public float getAvg(float[] var) {
            float sum = 0.0f;
            int cnt = 0;
            foreach (float x in var) {
                if(x>0) {
                    sum += x;
                    cnt++;
                }
            }
            
            return sum / cnt;
        }

        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            Viewport vp = ScreenManager.GraphicsDevice.Viewport;

            spriteBatch.Begin();
            /* INTERFACE */

            #region Your Score
            spriteBatch.DrawString(gameFont, "Your Score:", new Vector2(10), Color.GreenYellow);
            
            String str = "";
            for(int i = 0; i < score.Length; i++) {
                if(score[i] == 0) str += "\n" + (i+1) + ". --";
                else str += "\n" + (i+1) + ". " + score[i] + "s";
            }
            spriteBatch.DrawString(scoreFont, str, new Vector2(10, 10 + gameFont.MeasureString("Your Score:").Y), Color.FloralWhite);
            if(getAvg(score) > 0)
                spriteBatch.DrawString(scoreFont, "Average: " + getAvg(score) + "s", new Vector2(10, 10 + gameFont.MeasureString("Your Scores:").Y + scoreFont.MeasureString(str).Y), Color.LawnGreen);
            #endregion Your Score

            #region High Score
            spriteBatch.DrawString(gameFont, "High Score:", new Vector2(vp.Width - gameFont.MeasureString("High Score:").X - 10, 10), Color.GreenYellow);

            str = "";
            for (int i = 0; i < highscore.Length; i++) {
                if (highscore[i] == 0) str += "\n" + (i + 1) + ". --";
                else str += "\n" + (i + 1) + ". " + highscore[i] + "s";
            }
            spriteBatch.DrawString(scoreFont, str, new Vector2(vp.Width - scoreFont.MeasureString(str).X - 10, 10 + gameFont.MeasureString("High Score:").Y), Color.FloralWhite);
            if (getAvg(highscore) > 0)
                spriteBatch.DrawString(scoreFont, "Average: " + getAvg(highscore) + "s", new Vector2(vp.Width - scoreFont.MeasureString("Average: " + getAvg(highscore) + "s").X - 10, 10 + gameFont.MeasureString("High Score:").Y + scoreFont.MeasureString(str).Y), Color.LawnGreen);
            #endregion High Score

            


            if(!running)
                spriteBatch.DrawString(gameFont, "Press Enter to Start!", new Vector2(vp.Width / 2 - gameFont.MeasureString("Press Enter to Start!").X / 2, vp.Height / 2), Color.FloralWhite);
            else if(wait)
                spriteBatch.DrawString(gameFont, "Wait...", new Vector2(vp.Width / 2 - gameFont.MeasureString("Wait...").X / 2, vp.Height / 2), Color.Goldenrod);
            else
                spriteBatch.DrawString(gameFont, "GO!", new Vector2(vp.Width / 2 - gameFont.MeasureString("GO!").X / 2, vp.Height / 2), Color.LawnGreen);

            /* INTERFACE */
            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }


        #endregion
    }
}
